package main

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"gitee.com/zhucheer/orange/generator/tpl"
	"gitee.com/zhucheer/orange/utils"
	"gitee.com/zhucheer/orange/view"
	"io/ioutil"
	"os"
	"strings"
)

func main() {
	fmt.Println("run")
	argNum := len(os.Args)

	if argNum == 2 {
		secondArg := os.Args[1]
		switch secondArg {
		case "build":
			buildProject()
		}
	}

	if argNum >= 3 {
		secondArg := os.Args[1]
		inputArg := os.Args[2]
		switch secondArg {
		case "create":
			createProject(inputArg)
		}

	}
}

var gitignoreTpl = `*
!.gitignore
`

func createProject(projectName string) {
	fmt.Println("create project" + projectName)

	projectPath := getProjectPath(projectName)

	err := os.Mkdir(projectPath, os.ModePerm)
	if err != nil {
		fmt.Println(fmt.Sprintf("create project error:%v", err))
		return
	}
	fmt.Println("create directory [" + projectPath + "]")

	projectDir := []string{"config", "storage" + utils.DirDot() + "views", "build", "route", "http" + utils.DirDot() + "controller", "http" + utils.DirDot() + "middleware"}
	for _, item := range projectDir {
		subDir := getProjectPath(projectName, item)
		fmt.Println("create directory [" + subDir + "]")

		err := os.MkdirAll(subDir, os.ModePerm)
		if err != nil {
			fmt.Println(fmt.Sprintf("create project dir error:%v", err))
		}
	}

	writeMainFile(projectName)
	writeStorage(projectName)
	writeBuildDir(projectName)
	writeConfigFile(projectName)
	writeRouteFile(projectName)
	writeIndexFile(projectName)
	writeMiddlewareFile(projectName)
	fmt.Println("create project success!")
}

func writeBuildDir(projectName string) {
	gitignoreTpl = strings.Replace(gitignoreTpl, "\n", "", 1)
	path := getProjectPath(projectName, "build", ".gitignore")

	err := ioutil.WriteFile(path, []byte(gitignoreTpl), 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("create file [" + path + "]")
}

func writeStorage(projectName string) {
	demoTpl := parseTpl("tpldemo", map[string]interface{}{})
	path := getProjectPath(projectName, "storage", "views", "demo.tpl")

	err := ioutil.WriteFile(path, []byte(demoTpl), 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("create file [" + path + "]")
}

func writeMainFile(projectName string) {

	viewData := map[string]interface{}{
		"projectName": projectName,
	}
	maingoTpl := parseTpl("main", viewData)
	mainPath := getProjectPath(projectName, "main.go")
	err := ioutil.WriteFile(mainPath, []byte(maingoTpl), 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("create file [" + mainPath + "]")

	jobgoTpl := parseTpl("job", viewData)
	jobPath := getProjectPath(projectName, "job.go")
	err = ioutil.WriteFile(jobPath, []byte(jobgoTpl), 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("create file [" + jobPath + "]")
}

func writeConfigFile(projectName string) {
	viewData := map[string]interface{}{
		"appkey": getRandAppKey(),
	}
	configTpl := parseTpl("config", viewData)
	path := getProjectPath(projectName, "config", "config.toml")

	err := ioutil.WriteFile(path, []byte(configTpl), 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("create file [" + path + "]")
}

func writeRouteFile(projectName string) {
	viewData := map[string]interface{}{
		"projectName": projectName,
	}
	httpRoutesTpl := parseTpl("route", viewData)
	httppath := getProjectPath(projectName, "route", "http.go")

	err := ioutil.WriteFile(httppath, []byte(httpRoutesTpl), 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("create file [" + httppath + "]")

	jobRoutesTpl := parseTpl("jobRoute", viewData)
	jobpath := getProjectPath(projectName, "route", "job.go")

	err = ioutil.WriteFile(jobpath, []byte(jobRoutesTpl), 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("create file [" + jobpath + "]")

}

func writeIndexFile(projectName string) {
	indexHtml := parseTpl("indexhtml", map[string]interface{}{})
	viewData := map[string]interface{}{
		"indexHtml": indexHtml,
	}
	indexgoTpl := parseTpl("indexgo", viewData)
	path := getProjectPath(projectName, "http", "controller", "index.go")

	err := ioutil.WriteFile(path, []byte(indexgoTpl), 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("create file [" + path + "]")
}

func writeMiddlewareFile(projectName string) {
	viewData := map[string]interface{}{}
	middlewareTpl := parseTpl("middleware", viewData)
	path := getProjectPath(projectName, "http", "middleware", "auth.go")

	err := ioutil.WriteFile(path, []byte(middlewareTpl), 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("create file [" + path + "]")
}

func getProjectPath(subdirs ...string) string {
	basepath := getGoPath()

	for _, item := range subdirs {
		basepath = basepath + utils.DirDot() + item

	}

	return basepath
}

func getGoPath() string {
	stdout, _ := utils.ExecShell("go env GOPATH")
	stdout = strings.Replace(stdout, "\n", "", -1)
	return stdout + utils.DirDot() + "src"
}

func getRandAppKey() string {
	randByte := utils.RandomCreateBytes(24)
	h := md5.New()
	h.Write(randByte)
	return hex.EncodeToString(h.Sum(nil))
}

func parseTpl(fileName string, viewData interface{}) string {
	tplContent := tpl.GetTmp(fileName)

	return view.TextContent(tplContent, viewData)
}
